package com.ali.resource.ServicePage;

import com.ali.resource.CompoentPage.DnsPrivateZoneComponent;
import com.ali.resource.CompoentPage.DnsPublicZoneComponent;
import com.ali.resource.MapPage.dns.DnsPrivateZoneMap;
import com.ali.resource.MapPage.dns.DnsPrivateZoneRecordMap;
import com.ali.resource.MapPage.dns.DnsPublicDomainMap;
import com.ali.resource.MapPage.dns.DnsPublicDomainRecordMap;
import com.ali.resource.ShareTools.BasicTools;
import com.aliyun.alidns20150109.models.*;
import com.aliyun.pvtz20180101.models.DescribeZoneRecordsRequest;
import com.aliyun.pvtz20180101.models.DescribeZoneRecordsResponseBody;
import com.aliyun.pvtz20180101.models.DescribeZonesResponse;
import com.aliyun.pvtz20180101.models.DescribeZonesResponseBody;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestParam;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Component
public class DnsService {

    @Autowired
    private DnsPublicZoneComponent dnsPublicZoneComponent;

    @Autowired
    private BasicTools basicTools;

    @Autowired
    private DnsPrivateZoneComponent dnsPrivateZoneComponent;


    public List<DnsPublicDomainMap> getDnsDomains(
             @RequestParam(required = false) String domainNamePrefix) throws Exception {
        DescribeDomainsResponse domainResponse = dnsPublicZoneComponent.getDomainResponse();
        ArrayList<DnsPublicDomainMap> dnsPublicZoneMaps = new ArrayList<>();

        List<DescribeDomainsResponseBody.DescribeDomainsResponseBodyDomainsDomain> domain = domainResponse.getBody().getDomains().getDomain();
        for (DescribeDomainsResponseBody.DescribeDomainsResponseBodyDomainsDomain describeDomainsResponseBodyDomainsDomain : domain) {

            if (domainNamePrefix != null && describeDomainsResponseBodyDomainsDomain.getDomainName().toLowerCase().contains(domainNamePrefix)) {
                DnsPublicDomainMap build = DnsPublicDomainMap.builder().domainName(describeDomainsResponseBodyDomainsDomain.getDomainName()
                ).domainId(describeDomainsResponseBodyDomainsDomain.getDomainId()
                ).punyCode(describeDomainsResponseBodyDomainsDomain.getPunyCode()
                ).instanceId(describeDomainsResponseBodyDomainsDomain.getInstanceId()).build();

                dnsPublicZoneMaps.add(build);
            } else if (domainNamePrefix == null){
                DnsPublicDomainMap build = DnsPublicDomainMap.builder().domainName(describeDomainsResponseBodyDomainsDomain.getDomainName()
                ).domainId(describeDomainsResponseBodyDomainsDomain.getDomainId()
                ).punyCode(describeDomainsResponseBodyDomainsDomain.getPunyCode()
                ).instanceId(describeDomainsResponseBodyDomainsDomain.getInstanceId()).build();

                dnsPublicZoneMaps.add(build);
            }
        }

        return dnsPublicZoneMaps;
    }

    public List<DnsPublicDomainRecordMap> getDnsDomainRecords(
            @RequestParam(required = true,defaultValue = "false") String bool
            , @RequestParam(required = false) String hostnamePrefix
            , @RequestParam(required = false) String type
            , String domainName) throws Exception {

        DescribeDomainRecordsRequest domainRecord = dnsPublicZoneComponent.getDomainRecord(domainName);
        DescribeDomainRecordsResponse domainRecordResponse = dnsPublicZoneComponent.getDomainRecordResponse(domainRecord);
        Long totalCount = domainRecordResponse.getBody().totalCount;


        long Long = (totalCount / 50);
        if (0 != (totalCount % 50)) {
           Long += 1;
        }

        ArrayList<DnsPublicDomainRecordMap> dnsPublicDomainRecordMaps = new ArrayList<>();


        for (long l = 0; l < Long; l++) {
            domainRecord.setPageNumber(l+1L);
            domainRecord.setPageSize(50L);
            DescribeDomainRecordsResponse domainRecords = dnsPublicZoneComponent.getDomainRecordResponse(domainRecord);
            List<DescribeDomainRecordsResponseBody.DescribeDomainRecordsResponseBodyDomainRecordsRecord> record = domainRecords.getBody().getDomainRecords().getRecord();
            for (DescribeDomainRecordsResponseBody.DescribeDomainRecordsResponseBodyDomainRecordsRecord recordInfo : record) {
                DnsPublicDomainRecordMap dnsPublicDomainRecordMap = this.getDnsPublicDomainRecordMap(recordInfo);

                if (hostnamePrefix != null && type != null){

                    if (dnsPublicDomainRecordMap.getHostName().toLowerCase().contains(hostnamePrefix.toLowerCase().trim()) && dnsPublicDomainRecordMap.getType().toLowerCase().equals(type.toLowerCase().trim())){
                        dnsPublicDomainRecordMaps.add(dnsPublicDomainRecordMap);
                    }

                } else if (hostnamePrefix != null && type == null){

                    if (dnsPublicDomainRecordMap.getDomainName().toLowerCase().contains(hostnamePrefix.toLowerCase().trim())){
                        dnsPublicDomainRecordMaps.add(dnsPublicDomainRecordMap);
                    }

                } else if (type != null && hostnamePrefix == null){

                    if (dnsPublicDomainRecordMap.getType().toLowerCase().equals(type.toLowerCase().trim())){
                        dnsPublicDomainRecordMaps.add(dnsPublicDomainRecordMap);
                    }

                } else if (hostnamePrefix == null && type == null){
                    dnsPublicDomainRecordMaps.add(dnsPublicDomainRecordMap);
                }

            }
        }


        return dnsPublicDomainRecordMaps;
    }

    public DnsPublicDomainRecordMap getDnsPublicDomainRecordMap(DescribeDomainRecordsResponseBody.DescribeDomainRecordsResponseBodyDomainRecordsRecord recordInfo){
        DnsPublicDomainRecordMap build = DnsPublicDomainRecordMap.builder()
                .domainName(recordInfo.getDomainName())
                .status(recordInfo.getStatus())
                .type(recordInfo.getType())
                .hostName(recordInfo.getRR()+"."+recordInfo.getDomainName())
                .value(recordInfo.getValue())
                .build();

        return build;
    }

    public void getExecl(List<DnsPublicDomainRecordMap> records) throws IOException {
        XSSFWorkbook sheets = new XSSFWorkbook();
        XSSFSheet sheet = sheets.createSheet();
        XSSFRow row = sheet.createRow(0);

        row.createCell(0).setCellValue("domainName");
        row.createCell(1).setCellValue("status");
        row.createCell(2).setCellValue("type");
        row.createCell(3).setCellValue("hostName");
        row.createCell(4).setCellValue("value");

        int number = 1;
        for (DnsPublicDomainRecordMap recordMaps : records) {
            XSSFRow row1 = sheet.createRow(number);
            row1.createCell(0).setCellValue(recordMaps.getDomainName());
            row1.createCell(1).setCellValue(recordMaps.getStatus());
            row1.createCell(2).setCellValue(recordMaps.getType());
            row1.createCell(3).setCellValue(recordMaps.getHostName());
            row1.createCell(4).setCellValue(recordMaps.getValue());


            number += 1;
        }

        File file = BasicTools.setFIlePath("dnsRecords.xlsx");

        FileOutputStream fileOutputStream = new FileOutputStream(file);
        sheets.write(fileOutputStream);
        fileOutputStream.close();
        sheets.close();
    }

    public List<DnsPrivateZoneMap> getPrivateZoneList(@RequestParam(required = false) String zoneNamePrefix) throws Exception {

        ArrayList<DnsPrivateZoneMap> dnsPrivateZoneList = new ArrayList<>();
        DescribeZonesResponse zoneResponse = dnsPrivateZoneComponent.getZoneResponse(dnsPrivateZoneComponent.getZoneRequest());
        List<DescribeZonesResponseBody.DescribeZonesResponseBodyZonesZone> zone = zoneResponse.getBody().getZones().getZone();
        for (DescribeZonesResponseBody.DescribeZonesResponseBodyZonesZone describeZonesResponseBodyZonesZone : zone) {
            if (zoneNamePrefix != null && describeZonesResponseBodyZonesZone.getZoneName().toLowerCase().contains(zoneNamePrefix)){
                DnsPrivateZoneMap build = DnsPrivateZoneMap.builder().zoneName(describeZonesResponseBodyZonesZone.getZoneName())
                        .zoneId(describeZonesResponseBodyZonesZone.getZoneId())
                        .zoneType(describeZonesResponseBodyZonesZone.getZoneType())
                        .ProxyPattern(describeZonesResponseBodyZonesZone.getProxyPattern()).build();

                dnsPrivateZoneList.add(build);
            } else if (zoneNamePrefix == null) {
                DnsPrivateZoneMap build = DnsPrivateZoneMap.builder().zoneName(describeZonesResponseBodyZonesZone.getZoneName())
                        .zoneId(describeZonesResponseBodyZonesZone.getZoneId())
                        .zoneType(describeZonesResponseBodyZonesZone.getZoneType())
                        .ProxyPattern(describeZonesResponseBodyZonesZone.getProxyPattern()).build();

                dnsPrivateZoneList.add(build);
            }
        }
        return dnsPrivateZoneList;
    }

    public List<DnsPrivateZoneRecordMap> getDnsPrivateZoneRecords(
            @RequestParam(required = true,defaultValue = "false") String bool
            , @RequestParam(required = false) String hostnamePrefix
            , @RequestParam(required = false) String type
            , String zoneName) throws Exception {
        DescribeZoneRecordsRequest zoneRecordRequest = dnsPrivateZoneComponent.getZoneRecordRequest(zoneName);
        Integer totalItems = dnsPrivateZoneComponent.getZoneRecordResponse(zoneRecordRequest).getBody().getTotalItems();

        int page = totalItems / 20;
        if (page != (totalItems % 20)){
            page += 1;
        }



        ArrayList<DnsPrivateZoneRecordMap> privateRecordMaps = new ArrayList<>();

        for (int i = 1; i < page + 1; i++) {
            zoneRecordRequest.setPageNumber(i);
            zoneRecordRequest.setPageSize(20);
            List<DescribeZoneRecordsResponseBody.DescribeZoneRecordsResponseBodyRecordsRecord> record = dnsPrivateZoneComponent.getZoneRecordResponse(zoneRecordRequest).getBody().getRecords().getRecord();
            for (DescribeZoneRecordsResponseBody.DescribeZoneRecordsResponseBodyRecordsRecord describeZoneRecordsResponseBodyRecordsRecord : record) {
                DnsPrivateZoneRecordMap privateZoneRecordMap = this.getPrivateZoneMap(describeZoneRecordsResponseBodyRecordsRecord,zoneName);

                if (hostnamePrefix != null && type != null){

                    if (describeZoneRecordsResponseBodyRecordsRecord.getRr().toLowerCase().contains(hostnamePrefix.toLowerCase().trim()) && describeZoneRecordsResponseBodyRecordsRecord.getType().toLowerCase().equals(type.toLowerCase().trim())){
                        privateRecordMaps.add(privateZoneRecordMap);
                    }

                } else if (hostnamePrefix != null && type == null){

                    if (describeZoneRecordsResponseBodyRecordsRecord.getRr().toLowerCase().contains(hostnamePrefix.toLowerCase().trim())){
                        privateRecordMaps.add(privateZoneRecordMap);
                    }

                } else if (type != null && hostnamePrefix == null){

                    if (describeZoneRecordsResponseBodyRecordsRecord.getType().toLowerCase().equals(type.toLowerCase().trim())){
                        privateRecordMaps.add(privateZoneRecordMap);
                    }

                } else if (hostnamePrefix == null && type == null){
                    privateRecordMaps.add(privateZoneRecordMap);
                }

            }
        }

        return privateRecordMaps;
    }

    public DnsPrivateZoneRecordMap getPrivateZoneMap(DescribeZoneRecordsResponseBody.DescribeZoneRecordsResponseBodyRecordsRecord record ,String zoneName) throws Exception {


        String names = "";
        List<DescribeZonesResponseBody.DescribeZonesResponseBodyZonesZone> zone = dnsPrivateZoneComponent.getZoneResponse(dnsPrivateZoneComponent.getZoneRequest()).getBody().getZones().getZone();
        for (DescribeZonesResponseBody.DescribeZonesResponseBodyZonesZone describeZonesResponseBodyZonesZone : zone) {
            if (describeZonesResponseBodyZonesZone.getZoneId().equals(zoneName)){
                names = describeZonesResponseBodyZonesZone.getZoneName();
                break;
            }
        }
        DnsPrivateZoneRecordMap build = DnsPrivateZoneRecordMap.builder().zoneId(record.getZoneId())
                .zoneName(names)
                .status(record.getStatus())
                .type(record.getType())
                .hostName(record.getRr() + "." + names)
                .value(record.getValue()).build();
        return build;

    }


    public void getPrivateExecl(List<DnsPrivateZoneRecordMap> privateZoneMaps) throws IOException {
        XSSFWorkbook sheets = new XSSFWorkbook();
        XSSFSheet sheet = sheets.createSheet();
        XSSFRow row = sheet.createRow(0);

        row.createCell(0).setCellValue("zoneName");
        row.createCell(1).setCellValue("zoneId");
        row.createCell(2).setCellValue("status");
        row.createCell(3).setCellValue("type");
        row.createCell(4).setCellValue("hostName");
        row.createCell(5).setCellValue("value");

        int number = 1;
        for (DnsPrivateZoneRecordMap recordMaps : privateZoneMaps) {
            XSSFRow row1 = sheet.createRow(number);
            row1.createCell(0).setCellValue(recordMaps.getZoneName());
            row1.createCell(1).setCellValue(recordMaps.getZoneId());
            row1.createCell(2).setCellValue(recordMaps.getStatus());
            row1.createCell(3).setCellValue(recordMaps.getType());
            row1.createCell(4).setCellValue(recordMaps.getHostName());
            row1.createCell(5).setCellValue(recordMaps.getValue());


            number += 1;
        }

        File file = BasicTools.setFIlePath("dnsPrivateRecords.xlsx");

        FileOutputStream fileOutputStream = new FileOutputStream(file);
        sheets.write(fileOutputStream);
        fileOutputStream.close();
        sheets.close();
    }

}
